/*
 * Copyright (C) 2021 Baidu, Inc. All Rights Reserved.
 */
package com.chukun.rpc.protocol.codec;

import java.util.List;

import com.chukun.rpc.core.TinyRpcRequest;
import com.chukun.rpc.core.TinyRpcResponse;
import com.chukun.rpc.protocol.protocol.MessageHeader;
import com.chukun.rpc.protocol.protocol.MessageType;
import com.chukun.rpc.protocol.protocol.ProtocolConstants;
import com.chukun.rpc.protocol.protocol.TinyRpcProtocol;
import com.chukun.rpc.protocol.serialization.SerializationFactory;
import com.chukun.rpc.protocol.serialization.TinyRpcSerialization;
import com.sun.corba.se.spi.ior.iiop.IIOPFactories;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.MessageSizeEstimator;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>rpc框架解码器<p/>
 *
 * @author chukun
 * @version 1.0
 * @since 1.0-SNAPSHOT
 */
@Slf4j
public class TinyRpcDecoder extends ByteToMessageDecoder {

    /*
    +---------------------------------------------------------------+
    | 魔数 2byte | 协议版本号 1byte | 序列化算法 1byte | 报文类型 1byte  |
    +---------------------------------------------------------------+
    | 状态 1byte |        消息 ID 8byte     |      数据长度 4byte     |
    +---------------------------------------------------------------+
    |                   数据内容 （长度不定）                          |
    +---------------------------------------------------------------+
    */

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> out)
            throws Exception {
        log.info("TinyRpcDecoder decode data arrival......");
        if (in.readableBytes() < ProtocolConstants.HEADER_TOTAL_LEN) {
            return;
        }
        // 保存读取的标志位
        in.markReaderIndex();

        // 读取魔数
        short magic = in.readShort();
        if (ProtocolConstants.MAGIC != magic) {
            throw new IllegalArgumentException("Magic number is illegal, " + magic);
        }

        // 读取其它的header信息
        byte version = in.readByte();
        byte serializeType = in.readByte();
        byte msgType = in.readByte();
        byte status = in.readByte();
        long requestId = in.readLong();

        int dataLength = in.readInt();
        if (in.readableBytes() < dataLength) {
            in.resetReaderIndex();
            return;
        }
        byte[] data = new byte[dataLength];
        in.readBytes(data);

        MessageType messageType = MessageType.getByType(msgType);
        if (messageType == null) {
            return;
        }

        // 构造消息头
        MessageHeader header = new MessageHeader();
        header.setMagic(magic);
        header.setVersion(version);
        header.setSerialization(serializeType);
        header.setStatus(status);
        header.setRequestId(requestId);
        header.setMessageType(msgType);
        header.setMessageLen(dataLength);

        TinyRpcSerialization serialization =
                SerializationFactory.getInstance().getSerializationByType(serializeType);

        switch (messageType) {
            case REQUEST:
                TinyRpcRequest request = serialization.deserialize(data, TinyRpcRequest.class);
                if (request !=null) {
                    TinyRpcProtocol<TinyRpcRequest> protocol = new TinyRpcProtocol<>();
                    protocol.setHeader(header);
                    protocol.setBody(request);
                    out.add(protocol);
                }
                break;
            case RESPONSE:
                TinyRpcResponse response = serialization.deserialize(data, TinyRpcResponse.class);
                if (response != null) {
                    TinyRpcProtocol<TinyRpcResponse> protocol = new TinyRpcProtocol<>();
                    protocol.setHeader(header);
                    protocol.setBody(response);
                    out.add(protocol);
                }
                break;
            case HEARTBEAT:
                // TODO
                break;
        }
    }
}
